#include <iostream>
#include <vector>

/*
① 首先，如果为你的类或者类模版提供的swap默认实现版本在效率上可以满足你，你就什么都不需要做。
任何人尝试对你定义类型的对象进行swap，只要调用默认版本就可以了，这会工作的很好。
 ② 其次，如果swap的默认实现在效率上达不到你的要求（通常就意味着你的类或者类模板在使用同指向实现的指针（pimpl idiom）类似的变量），那么按照下面的去做：

1、提供一个 public 的swap成员函数，对你的类型的两个对象值可以高效的swap。原因一会解释，这个函数永远不应该抛出异常。

2、在与你的类或模板相同的命名空间中提供一个非成员swap。让它调用你的swap成员函数版本。

3、如果你正在实现一个类（不是一个类模版），为你的类特化std::swap。让他也调用你的swap成员函数版本。

4、最后，如果你调用swap，确保在你的函数中include一个using声明来使得std::swap是可见的，然后调用swap时不要加std命名空间对其进行限定。

*/




//std中实现了swap函数
//只要实现copy构造函数的变量都可以使用std::swap实行交换

//这里需要探讨的是效率问题

//如果交换两个Window对象：我们只需要交换WindowImpl的指针就好了，但是使用std::swap的话，就会调用三次copy构造函数，效率很低

/*
    //STL中swap函数源码
namespace std {
	template<typename T> 
	void swap(T& a, T& b) 
	{
		T temp(a);
		a = b;
		b = temp;
	}
}

*/

class WindowImpl
{
    private:
    int a,b,c,d,e;//...
    std::vector<int>a;//意味着复制很麻烦
};

class Window
{
public:
    void swap(Window& rhs)
    {
        using std::swap;        //为什么要有这个声明，见下
        swap(pImpl, rhs.pImpl); //调用std::swap()函数，只交换两个对象的指针
    }

private:
    WindowImpl *pImpl;
};

//1、实现一个全特化的swap
//此swap用于表示这个函数针对“T是Window”而设计的
namespace std {
    //template<>用于表示这是一个std::Swap的全特化版本
    template<>
    void swap<Widget>(Window& a, Window& b) 
    {
        //错误的，pImpl是private的，无法编译通过
        //swap(a.pImpl, b.pImpl);

        a.swap(b);//将swap设置为成员函数
    }
}


int main(int argc, char const *argv[])
{
    int a = 10, b = 20;
    std::cout << " Before swap a = " << a << std::endl;
    std::cout << " Before swap b = " << b << std::endl;
    std::swap(a, b);
    std::cout << "a = " << a << std::endl;
    std::cout << "b = " << b << std::endl;

    int d;//默认构造函数
    d = a;//复制构造函数

    int c(a);//直接调用初始化序列表
    return 0;
}
